// Copyright 2017 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CORE_FPDFAPI_PARSER_CPDF_OBJECT_WALKER_H_
#define CORE_FPDFAPI_PARSER_CPDF_OBJECT_WALKER_H_

#include <memory>
#include <stack>

#include "core/fxcrt/bytestring.h"
#include "core/fxcrt/retain_ptr.h"

class CPDF_Object;

// Walk on all non-null sub-objects in an object in depth, include itself,
// like in flat list.
class CPDF_ObjectWalker {
 public:
  class SubobjectIterator {
   public:
    virtual ~SubobjectIterator();
    virtual bool IsFinished() const = 0;
    bool IsStarted() const { return is_started_; }
    RetainPtr<const CPDF_Object> Increment();
    const CPDF_Object* object() const { return object_.Get(); }

   protected:
    explicit SubobjectIterator(RetainPtr<const CPDF_Object> object);

    virtual RetainPtr<const CPDF_Object> IncrementImpl() = 0;
    virtual void Start() = 0;

   private:
    RetainPtr<const CPDF_Object> object_;
    bool is_started_ = false;
  };

  explicit CPDF_ObjectWalker(RetainPtr<const CPDF_Object> root);
  ~CPDF_ObjectWalker();

  RetainPtr<const CPDF_Object> GetNext();
  void SkipWalkIntoCurrentObject();

  size_t current_depth() const { return current_depth_; }
  const CPDF_Object* GetParent() const { return parent_object_.Get(); }
  const ByteString& dictionary_key() const { return dict_key_; }

 private:
  static std::unique_ptr<SubobjectIterator> MakeIterator(
      RetainPtr<const CPDF_Object> object);

  RetainPtr<const CPDF_Object> next_object_;
  RetainPtr<const CPDF_Object> parent_object_;
  ByteString dict_key_;
  size_t current_depth_ = 0;
  std::stack<std::unique_ptr<SubobjectIterator>> stack_;
};

class CPDF_NonConstObjectWalker final : public CPDF_ObjectWalker {
 public:
  explicit CPDF_NonConstObjectWalker(RetainPtr<CPDF_Object> root);
  RetainPtr<CPDF_Object> GetNext();
};

#endif  // CORE_FPDFAPI_PARSER_CPDF_OBJECT_WALKER_H_
`CPDF_ObjectWalker` 和 `CPDF_NonConstObjectWalker` 类提供了对 PDF 对象及其子对象的递归遍历接口。以下是这些类的接口功能：

### 类 `CPDF_ObjectWalker`

#### 嵌套类 `SubobjectIterator`
1. * *Virtual Destructor * *: `~SubobjectIterator()` - 虚析构函数。

2. * *bool IsFinished() const** -检查迭代器是否已完成。

3. * *bool IsStarted() const** -检查迭代器是否已启动。

4. * *RetainPtr<const CPDF_Object> Increment() * *-移动到下一个子对象。

5. * *const CPDF_Object * object() const** -获取当前迭代指向的对象。

#### 构造函数
6. * *explicit SubobjectIterator(RetainPtr<const CPDF_Object> object) * *-使用对象指针初始化。

#### 纯虚函数（子类需要实现）
7. * *virtual RetainPtr<const CPDF_Object> IncrementImpl() = 0 * *-增量实现。

8. * *virtual void Start() = 0 * *-启动迭代器。

#### 主类 `CPDF_ObjectWalker`

#### 构造函数与析构函数
9. * *explicit CPDF_ObjectWalker(RetainPtr<const CPDF_Object> root) * *-使用根对象初始化遍历器。

10. * *~CPDF_ObjectWalker() * *-析构函数。

#### 方法
11. * *RetainPtr<const CPDF_Object> GetNext() * *-获取下一个对象。

12. * *void SkipWalkIntoCurrentObject() * *-跳过遍历当前对象的子对象。

13. * *size_t current_depth() const** -获取当前遍历深度。

14. * *const CPDF_Object * GetParent() const** -获取当前遍历对象的父对象。

15. * *const ByteString & dictionary_key() const** -获取当前字典项的关键字。

#### 静态方法
16. * *static std::unique_ptr<SubobjectIterator> MakeIterator(RetainPtr<const CPDF_Object> object) * *-创建子对象迭代器。

### 类 `CPDF_NonConstObjectWalker`

#### 构造函数
17. * *explicit CPDF_NonConstObjectWalker(RetainPtr<CPDF_Object> root) * *-使用可修改的根对象初始化遍历器。

#### 方法
18. * *RetainPtr<CPDF_Object> GetNext() * *-获取下一个可修改的对象。

以上接口提供了对 PDF 对象的深度优先遍历功能，使用户能够按顺序访问和处理对象及其子对象。`CPDF_NonConstObjectWalker` 类扩展了 `CPDF_ObjectWalker`，允许操作可变对象，使得遍历过程中的对象可以被修改。